<template>
  <div class="roleHeader">
    <a-row :gutter="[16, 16]" class="search">
      <a-col :span="4">
        <a-input v-model:value="SearchInfo.name" placeholder="角色"/>
      </a-col>
      <a-col :span="4" class="btn">
        <a-button :icon="h(SearchOutlined)" type="primary" @click="searchUser"
        >搜索
        </a-button
        >
        <a-button :icon="h(RedoOutlined)" @click="restTable">重置</a-button>
      </a-col>
    </a-row>
  </div>
  <div class="roleContainer">
    <Table ref="TableRef" v-model:formState="formState" :columns="columns" :data="TableData"
           :refresh="get_TableData" :resetForm="resetForm" :tableHeaderButton="tableHeaderButton">
      <a-form
          ref="formRef"
          :label-col="labelCol"
          :model="formState"
          :rules="rules"
          :wrapper-col="wrapperCol"
      >

        <a-form-item ref="role" label="角色" name="name">
          <a-input v-model:value="formState.name" placeholder="角色"/>
        </a-form-item>
        <a-form-item ref="role" label="角色描述名" name="code">
          <a-input v-model:value="formState.code" placeholder="角色描述名"/>
        </a-form-item>
        <a-form-item ref="role" label="说明" name="remark">
          <a-input v-model:value="formState.remark" placeholder="说明"/>
        </a-form-item>
        <a-form-item :wrapper-col="{ span: 24}">
          <div style="width: 100%;display: flex;align-items: center;justify-content: end;">
            <a-button style="margin: 0 20px" @click="close">取消</a-button>
            <a-button type="primary" @click="onSubmit">提交</a-button>
          </div>
        </a-form-item>
      </a-form>
    </Table>
    <div class="tree">
      <div class="treeHeader">
        <h2 style="font-size: 18px;font-weight: 600;color: #303133;padding: 10px">分配菜单权限</h2>
        <a-button type="primary" @click="saveTreeData">
          <template #icon>
            <CheckOutlined/>
          </template>
          保存
        </a-button>
      </div>
      <a-tree
          v-model:checkedKeys="checkedKeys"
          :autoExpandParent="true"
          :checkStrictly="true"
          :tree-data="treeData"
          checkable
          @check="onCheck"
      >
        <template #title="{ title, key }">
          {{ title }}
        </template>
      </a-tree>

    </div>

  </div>
</template>

<script setup>
import {message} from "ant-design-vue";
import {
  addRole,
  delRole,
  FindUserMenu,
  get_menus,
  get_RoleAll,
  search_AuthAllUser,
  updateRole,
  updateUserMenus
} from "@/api/auth.js";
import {CheckOutlined, RedoOutlined, SearchOutlined} from "@ant-design/icons-vue";
import Table from "@/components/Table/index.vue";
import {h, onMounted, reactive, ref, toRaw} from "vue";
import {transformData} from "@/utils/handelTree.js";
import eventBus from "@/utils/eventBus.js";

let cruuentUserId = ref(0)
const TableRef = ref('')
let TableData = ref([]);
const formRef = ref();
const SearchInfo = reactive({
  name: "",
});
// 表单
const labelCol = {
  span: 6,
};
const wrapperCol = {
  span: 16,
};
// 表格配置项
const columns = [
  {
    title: "角色",
    key: "name",
    dataIndex: "name",
  },
  {
    title: "描述名",
    key: "code",
    dataIndex: "code",
    width: 150,
  },

  {
    title: "创建时间",
    key: "create_time",
    dataIndex: "create_time",
  },
  {
    title: "更新时间",
    key: "update_time",
    dataIndex: "update_time",
  },
  {
    title: "描述",
    key: "remark",
    dataIndex: "remark",
  },
  {
    title: "操作",
    key: "action",
    width: 150,
    btn: [{
      type: 'edit',
      key: ['id']
    },
      {
        type: 'del',
        callback: delRole,
        key: ['id']
      }],
  },
];
const tableHeaderButton = ['add', 'export', 'delete']
const formState = ref({
  name: '',
  code: '',
  remark: ''
});
const rules = {
  name: [
    {
      required: true,
      message: "请输入角色名",
      trigger: "change",
    },
  ],
  code: [
    {
      required: true,
      message: "请输入角色描述名",
      trigger: "change",
    },
  ],
  remark: [
    {
      required: true,
      message: "请补充该角色的说明",
      trigger: "change",
    },
  ],
};
// tree
let treeData = ref([]);
const checkedKeys = ref([]);
let isChange = ref(false)
// 搜索
const searchUser = async () => {
  if (SearchInfo.name) {
    message.error("查询不能为空");
    return;
  }
  let res = await search_AuthAllUser(toRaw(SearchInfo));
  if (!res) return;
  TableData.value = res.data;
};
// 重置table
const restTable = () => {
  SearchInfo.user = "";
  SearchInfo.role = "";
  get_TableData();
};
// 查询table数据
const get_TableData = async () => {
  let res = await get_RoleAll();
  if (!res) return;
  TableData.value = res.data;
};
// 关闭Model
const close = () => {
  TableRef.value.closeModel()
}
// 提交表单
const onSubmit = () => {
  const type = TableRef.value.statusType
  const data = TableRef.value.editId
  formRef.value
      .validate()
      .then(async () => {
        let res = await requestData(type, data)
        if (!res) return;
        if (res.status === 400) message.error(res.data)
        if (res.status === 200) message.success(res.data)
        // 重新请求数据
        await get_TableData()
        close()
        resetForm()
      })
      .catch((error) => {
        console.log("error", error);
      });
};
// 提交请求
const requestData = async (type, data) => {
  if (type === 'add') {
    return await addRole({...formState.value})
  }
  if (type === 'edit') {
    return await updateRole({...formState.value, ...data})
  } else {
    console.log('错误方式')
    return {data: '错误方式'}
  }
}
// 重置表单
const resetForm = () => {
  formState.value = {
    name: "",
    code: "",
    remark: ''
  }
};

// 提交树形菜单数据
const saveTreeData = async () => {
  let checkData = checkedKeys.value
  let res = await updateUserMenus({
    role_id: cruuentUserId.value,
    checkData
  })
  if (!res) return
  message.success(res.data)
}

// 获取每个用户的菜单权限
eventBus.on('rowClick', async (data) => {
  let id = data['id']
  // 更新当前用户id
  cruuentUserId.value = id
  await checkUserMenus(id)
})

// 查询用户所有的菜单权限
const checkUserMenus = async (id) => {
  let res = await FindUserMenu({id})
  if (!res) return
  expandTree(transformData(res.data))
}

// 用户权限赋值给tree
const expandTree = (data = []) => {
  checkedKeys.value = getAllKeys(data);
  setTimeout(() => {
    isChange.value = true
  }, 0)
}

// 获取所有的 key
const getAllKeys = (data) => {
  const keys = [];
  const traverse = (nodes) => {
    nodes.forEach(node => {
      keys.push(node.key);
      if (node.children) {
        traverse(node.children);
      }
    });
  };
  traverse(data);
  return keys;
};
//获取所有菜单
const getAllMenus = async () => {
  let res = await get_menus()
  if (!res) return
  treeData.value = transformData(res.data)
}
onMounted(() => {
  getAllMenus()
  get_TableData();
});

// tree点击选中
const onCheck = (checkedKeyList, e) => {
  const data = treeData.value;
  const targetKey = e.node.key;
  data.forEach(item => {
    if (item.key === targetKey && item.children) {
      const childKeys = item.children.map(child => child.key);
      checkedKeyList.checked = e.checked
          ? [...new Set([...checkedKeyList.checked, ...childKeys])]
          : checkedKeyList.checked.filter(key => !childKeys.includes(key));
    } else if (e.node.parent) {
      const parentKey = e.node.parent.key;
      const childKeys = e.node.parent.children;

      if (e.checked) {
        if (!checkedKeyList.checked.includes(parentKey)) {
          checkedKeyList.checked.push(parentKey);
        }
      } else if (!arraysIntersect(childKeys, checkedKeyList.checked)) {
        checkedKeyList.checked = checkedKeyList.checked.filter(key => key !== parentKey);
      }
    }
  });

  checkedKeys.value = checkedKeyList.checked;
}

// 判断两个数组是否存在交叉
function arraysIntersect(arr1, arr2) {
  return arr1.some(item => arr2.includes(item.key));
}

</script>

<style lang="scss" scoped>
.roleHeader {
  .search {
    .btn {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-evenly;
      gap: 15px;
    }
  }
}


.roleContainer {
  width: 100%;
  display: grid;
  grid-template-columns: 3fr 1fr;
  gap: 20px;

  .tree {
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: start;
    align-items: start;
    padding: 0 20px;
    background-color: #ffffff;
    border-radius: 5px;

    .treeHeader {
      width: 100%;
      display: flex;

      gap: 20px;
      align-items: center;
      justify-content: space-around;
    }
  }
}
</style>